package resolver

// This file will be automatically regenerated based on the schema, any resolver implementations
// will be copied through when generating and any unknown code will be moved to the end.

import (
	"context"
	"errors"
	"fmt"
	"strconv"

	"mall/service/blog/rpc/blogclient"
	"mall/service/wpgql/api/internal/graph/generated"
	"mall/service/wpgql/api/internal/graph/helper"
	"mall/service/wpgql/api/internal/graph/model"
	"mall/service/wpgql/api/internal/graph/util"
)

const blogPageSingleError = "could not get blog page"
const blogPageListError = "could not list blog pages"

func (r *mutationResolver) CreatePage(ctx context.Context, input model.CreatePageInput) (*model.CreatePagePayload, error) {
	panic(fmt.Errorf("not implemented"))
}

func (r *mutationResolver) DeletePage(ctx context.Context, input model.DeletePageInput) (*model.DeletePagePayload, error) {
	panic(fmt.Errorf("not implemented"))
}

func (r *mutationResolver) UpdatePage(ctx context.Context, input model.UpdatePageInput) (*model.UpdatePagePayload, error) {
	panic(fmt.Errorf("not implemented"))
}

func (r *pageResolver) Ancestors(ctx context.Context, obj *model.Page, first *int, last *int, after *string, before *string, where *model.HierarchicalContentNodeToContentNodeAncestorsConnectionWhereArgs) (*model.HierarchicalContentNodeToContentNodeAncestorsConnection, error) {
	panic(fmt.Errorf("not implemented"))
}

func (r *pageResolver) Children(ctx context.Context, obj *model.Page, first *int, last *int, after *string, before *string, where *model.HierarchicalContentNodeToContentNodeChildrenConnectionWhereArgs) (*model.HierarchicalContentNodeToContentNodeChildrenConnection, error) {
	panic(fmt.Errorf("not implemented"))
}

func (r *pageResolver) Comments(
	ctx context.Context,
	obj *model.Page,
	first *int,
	last *int,
	after *string,
	before *string,
	where *model.PageToCommentConnectionWhereArgs,
) (*model.PageToCommentConnection, error) {
	if where == nil {
		return obj.Comments, nil
	}

	return &model.PageToCommentConnection{}, nil
}

func (r *pageResolver) Content(ctx context.Context, obj *model.Page, format *model.PostObjectFieldFormatEnum) (*string, error) {
	var content string
	if obj != nil {
		if obj.Content != nil {
			content = *obj.Content
		}
	}

	return &content, nil
}

func (r *pageResolver) EnqueuedScripts(ctx context.Context, obj *model.Page, first *int, last *int, after *string, before *string) (*model.ContentNodeToEnqueuedScriptConnection, error) {
	panic(fmt.Errorf("not implemented"))
}

func (r *pageResolver) EnqueuedStylesheets(ctx context.Context, obj *model.Page, first *int, last *int, after *string, before *string) (*model.ContentNodeToEnqueuedStylesheetConnection, error) {
	panic(fmt.Errorf("not implemented"))
}

func (r *pageResolver) Revisions(
	ctx context.Context,
	obj *model.Page,
	first *int,
	last *int,
	after *string,
	before *string,
	where *model.PageToRevisionConnectionWhereArgs,
) (*model.PageToRevisionConnection, error) {
	if where == nil {
		return obj.Revisions, nil
	}

	return &model.PageToRevisionConnection{}, nil
}

func (r *pageResolver) Title(ctx context.Context, obj *model.Page, format *model.PostObjectFieldFormatEnum) (*string, error) {
	var title string
	if obj != nil {
		if obj.Title != nil {
			title = *obj.Title
		}
	}

	return &title, nil
}

func (r *queryResolver) Page(
	ctx context.Context,
	id string,
	idType *model.PageIDType,
	asPreview *bool,
) (*model.Page, error) {
	req := &blogclient.PageDetailRequest{}

	var preview bool
	if asPreview != nil {
		preview = *asPreview
	}
	req.AsPreview = preview

	preload, eagerLoad := helper.GetBlogPagePreloads(ctx)
	if preload != "" {
		req.Preload = preload
	}
	if eagerLoad != "" {
		req.EagerLoad = eagerLoad
	}
	filter := helper.GetBlogPageFilter(id, idType)
	if filter != "" {
		req.Filter = filter
	}

	res, err := r.svcCtx.BlogRpc.PageDetail(ctx, req)
	if err != nil {
		return nil, errors.New(blogPageSingleError)
	}

	return helper.BlogPageToGraphQL(res), nil
}

func emptyRootQueryToPageConnection() *model.RootQueryToPageConnection {
	return &model.RootQueryToPageConnection{
		Edges:    []*model.RootQueryToPageConnectionEdge{},
		Nodes:    []*model.Page{},
		PageInfo: &model.WPPageInfo{},
	}
}

func (r *queryResolver) Pages(
	ctx context.Context,
	first *int,
	last *int,
	after *string,
	before *string,
	where *model.RootQueryToPageConnectionWhereArgs,
) (*model.RootQueryToPageConnection, error) {
	req := &blogclient.PageListRequest{}

	preload, eagerLoad := helper.GetBlogPageNodesPreloads(ctx)
	if preload != "" {
		req.Preload = preload
	}
	if eagerLoad != "" {
		req.EagerLoad = eagerLoad
	}

	pagination := util.NewPagination(first, last, after, before,
		r.svcCtx.Config.Query.DefaultAmount, r.svcCtx.Config.Query.MaxAmount)

	var sorter []*model.PostObjectsConnectionOrderbyInput
	if where != nil {
		sorter = where.Orderby
	}
	sorterMap := helper.GetBlogPostConnectionSorterMap(pagination, sorter)
	var reverse bool
	if sorterMap != nil {
		for k, v := range sorterMap {
			switch k {
			case "offset":
				if i, err := strconv.ParseInt(v, 10, 32); err == nil {
					req.Offset = int32(i)
				}
			case "limit":
				if i, err := strconv.ParseInt(v, 10, 32); err == nil {
					req.Limit = int32(i)
				}
			case "sorter":
				req.Sorter = v
			case "reverse":
				if v == "1" {
					reverse = true
				}
			}
		}
	}

	filterMap := helper.GetBlogPageConnectionFilterMap(where)
	if filterMap != nil {
		for k, v := range filterMap {
			switch k {
			case "search":
				req.Search = v
			case "filter":
				req.Filter = v
			case "preFilterEntity":
				req.PreFilterEntity = v
			case "preFilter":
				req.PreFilter = v
			}
		}
	}

	res, err := r.svcCtx.BlogRpc.PageList(ctx, req)
	if err != nil {
		return &model.RootQueryToPageConnection{}, errors.New(blogPageListError)
	}

	if len(res.Data) > 0 {
		var pages []*model.Page
		for _, page := range res.Data {
			pages = append(pages, helper.BlogPageToGraphQL(page))
		}
		connection := helper.GetRootQueryToPageConnection(pages,
			res.HasNextPage > 0, res.HasPreviousPage > 0, req.Offset, reverse)
		return connection, nil
	}

	return emptyRootQueryToPageConnection(), nil
}

// Page returns generated.PageResolver implementation.
func (r *Resolver) Page() generated.PageResolver { return &pageResolver{r} }

type pageResolver struct{ *Resolver }
